#ifndef _FTP_SERVER_H
#define _FTP_SERVER_H

#include <stdio.h>
#include <sys/select.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <dirent.h>

#define PACK_SIZE (1024 - sizeof(int) * 3)

// 定义一个枚举，用来标识文件传输的状态
enum MSGFLAG
{
    MSG_FILE_NAME = 1,  //文件名
    MSG_FILE_SIZE = 2,  //文件大小
    MSG_READY = 3,     //准备接受标识
    MSG_SEND = 4,      //发送
    MSG_SUCCESSED = 5, //传输成功标识
    MSG_OPEN_FAILED = 6 //文件打开失败
};

// 封装消息头
#pragma pack(1)     // 设置该结构体 1 字节对齐
typedef struct h
{
    enum MSGFLAG msg_ID;        // 当前消息的标志信息
    union Myunion
    {
        struct f{
            int file_size;              // 4
            char filename[256];         // 256
        }FILE_INFO;                 // 定义一个文件信息的结构体
        
        struct x
        {
            int pack_No;                                    // 包的编号
            int n_size;                                     // 包的大小
            char file_buf[PACK_SIZE];             // 用来存放文件
        }Packet;
    } un;
}MSG_HEAD;
#pragma pack()		//对齐结束标志

// 用于保存当前服务端的工作目录
typedef struct w
{
    char dir_name[256];
}Work_Dir;


#define PORT 5005    // 通信端口
#define LISTEN_NUM 4 // 监听数

#define BUF_SIZE 1024

// char recv_buff[BUF_SIZE];         // 用来存放接收的消息
// char send_buff[BUF_SIZE];         // 用来存放发送的消息

// 监听客户端的连接
// 返回值：正常返回true     异常返回false
bool ftplisten_to_client(void);

//处理连接请求
// 参数说明：s accpet 成功后返回的文件描述符；
bool processMsg(int *clientfd);

// 获得文件名所对应的文件大小，并将其发送给客户端
// 返回值：成功返回true，失败返回false
bool readfile(int *clientfd, MSG_HEAD *pmsghead);

// 路径分离解析函数
// 参数说明：path：文件路径  drive：驱动器盘符 dir：中间的路径 fname：文件名 ext：后缀名
void _splitpath(const char *path, char *drive, char *dir, char *fname, char *ext);

// 配合_splitpath 使用的子函数
static void _split_whole_name(const char *whole_name, char *fname, char *ext);

// 从客户端接收到 MSG_SEND 服务器开始发送
bool serv_send_file(int clientfd, MSG_HEAD *pmsg);

// 文件传输成功
bool success_to_client(int clientfd);

// // 发送服务端程序运行的工作目录
// bool send_Dir_name(int clientfd);

// 接收客户端发送的 命令 并进行相关操作
bool get_cmd(int cliendfd);

bool send_file_msg(int clientfd,DIR *dir, char *path);

#endif